/*
	Copyright (c) 2007, ANYwebcam.com Pty Ltd. All rights reserved.

	The software in this package is published under the terms of the BSD style 
	license, a copy of which has been included with this distribution in the 
	license.txt file.
*/
package com.anywebcam.di.util
{
	import com.anywebcam.di.error.CyclicDependencyError;
	
	// fixme: Take into account that the key being requested may be higher in the inheritance chain then a type in the stack already, 
	// whereby the type already in the stack is the only known implementation of that key and as such should not be requestable 
	// as we havent yet created an instance of that type.
	// todo: draw a diagram of the above situation to explain clearer
	
	/**
	 * Guards against cyclic-dependencies between components
	 */
	public class CyclicDependencyGuard
	{
		private var _stack:Array;
		
		public function CyclicDependencyGuard()
		{
			_stack = [];
		}
		
		/**
		 * @return The Array of keys this guard is checking for cyclic-dependencies
		 */
		public function get stack():Array
		{
			return _stack;
		}
		
		/**
		 * @throws CyclicDependencyError When the key being guarded is already in the stack
		 */
		protected function checkForCyclicDependency( key:Object ):void
		{
			if( _stack.indexOf( key ) > -1 )
			{
				throw new CyclicDependencyError( key, stack );
			}
		}
		
		/**
		 * @param key The key to guard for cyclic-dependencies
		 */
		public function guard( key:Object ):void
		{
			checkForCyclicDependency( key );
			
			_stack.push( key );
		}
		
		/**
		 * @param key The key to stop guarding against cyclic-dependencies
		 * @throws CyclicDependencyError When the last key in the stack is not the key being unguarded
		 */
		public function unguard( key:Object ):void
		{
			if( _stack[ _stack.length - 1 ] != key )
			{
				throw new CyclicDependencyError( key, stack );
			}
			
			_stack.pop();
		}
	}
}